﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Precio.Logging.Facade.Config;
using Precio.Logging.Facade.Client;

namespace Kaskelot.SP.Core
{
    public static class Logger
    {
        private static string source = "Precio.Logging";

        public static void LogVerbose(object caller, string layer, string methodName, string message)
        {
            HealthCheck();
            Precio.Logging.Facade.Client.Logger.Write(System.Diagnostics.TraceEventType.Verbose, source, layer, GetCallerFriendly(caller), message, methodName, null);
            ULSLoggingService.LogVerboseMessage(GetErrorMessage(caller, layer, methodName, message, null));
        }

        public static void LogError(object caller, string layer, string methodName, string message, Exception exception)
        {
            HealthCheck();
            Precio.Logging.Facade.Client.Logger.Write(System.Diagnostics.TraceEventType.Error, source, layer, GetCallerFriendly(caller), message, methodName, exception);
            ULSLoggingService.LogError(GetErrorMessage(caller, layer, methodName, message, exception));
        }

        public static void LogInformation(object caller, string layer, string methodName, string message)
        {
            HealthCheck();
            Precio.Logging.Facade.Client.Logger.Write(System.Diagnostics.TraceEventType.Information, source, layer, GetCallerFriendly(caller), message, methodName, null);
            ULSLoggingService.LogVerboseMessage(GetErrorMessage(caller, layer, methodName, message, null));
        }

        public static void LogWarning(object caller, string layer, string methodName, string message)
        {
            HealthCheck();
            Precio.Logging.Facade.Client.Logger.Write(System.Diagnostics.TraceEventType.Warning, source, layer, GetCallerFriendly(caller), message, methodName, null);
            ULSLoggingService.LogError(GetErrorMessage(caller, layer, methodName, message, null));
        }

        public static string GetCurrentCorrelationID()
        {
            return Precio.Logging.Facade.SharePoint.Context.SharePointContext.GetCorrelationId();
        }

        public static void SetEndPointUri(string uri)
        {
            string processName = System.Diagnostics.Process.GetCurrentProcess().ProcessName;
            InitData initData = new InitData()
            {
                EndpointUri = uri,
                WriteInformationToEventLogOnFailure = false,
                WriteWarningToEventLogOnFailure = false,
                WriteActivityTracingToEventLogOnFailure = false,
                MultiThreadingAllowed = (processName == "w3wp" || processName == "powershell")
            };

            System.Diagnostics.SourceLevels loggingLevel = System.Diagnostics.SourceLevels.Off;
            try
            {
                loggingLevel = (System.Diagnostics.SourceLevels)Enum.Parse(typeof(System.Diagnostics.SourceLevels), ConfigManager.General.LoggingLevel);

                ConfigurationHelper.SetConfiguration(
                  source,
                  loggingLevel,
                  initData);
            }
            catch { }
        }

        private static string GetCallerFriendly(object caller)
        {
            if (caller == null)
                return "unkown";
            else if (caller.GetType() == typeof(string))
                return caller as string;
            else
                return caller.GetType().FullName;
        }

        private static void HealthCheck()
        {
            if (ConfigurationHelper.GetConfigurationSummary(source).Contains("Contract.Name=ILoggingService") == false)
            {
                string loggingLocation = ConfigManager.General.LoggingServiceLocation;

                if (!String.IsNullOrEmpty(loggingLocation))
                {
                    SetEndPointUri(loggingLocation);
                }
            }
        }

        private static string GetErrorMessage(object caller, string layer, string methodName, string message, Exception exception)
        {
            return string.Format("Error in {0}: {1}.{2}. ErrorMessage: {3}  Ex: {4}", layer, GetCallerFriendly(caller), methodName, message, exception != null ? exception.ToString() : string.Empty);
        }
    }
}
